package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"

	"gopkg.in/yaml.v3"
)

type Response struct {
	Status string `json:"status"`
	Data   struct {
		ResultType string `json:"resultType"`
		Result     []struct {
			Metric struct {
				HostIP string `json:"host_ip"`
			} `json:"metric"`
			Value []interface{} `json:"value"`
		} `json:"result"`
	} `json:"data"`
}

const (
	Cluster = "0"
	Node    = "1"
	Pod     = "2"
)

type Query struct {
	MetricName  string `yaml:"MetricName"`  //
	MetricScope string `yaml:"MetricScope"` // Cluster / Node / Pod
	PromQL      string `yaml:"PromQL"`
}

var (
	ROBOTKEY string
)

func main() {
	querys := []Query{
		// 	{"clusterCpuUse", Cluster, `(1-avg(irate(node_cpu_seconds_total{mode="idle"}[5m])))*100`},
		// 	{"clusterMemUse", Cluster, `(1-sum(node_memory_MemAvailable_bytes{})/sum(node_memory_MemTotal_bytes{}))*100`},
		// 	{"clusterDiskUse", Cluster, `(sum(node_filesystem_size_bytes{})-sum(node_filesystem_free_bytes{}))/sum(node_filesystem_size_bytes{})*100`},
		// 	{"nodeCpuUse", Node, `(1-(avg(irate(node_cpu_seconds_total{mode="idle"}[5m]))by(host_ip)))*100`},
		// 	{"nodeMemUse", Node, `(1-(sum(node_memory_MemAvailable_bytes{})by(host_ip)/(sum(node_memory_MemTotal_bytes{})by(host_ip))))*100`},
		// 	{"nodeDiskUse", Node, `(sum(node_filesystem_size_bytes{device=~"/dev/vda1"})by(device,host_ip)-sum(node_filesystem_free_bytes{})by(device,host_ip))/(sum(node_filesystem_size_bytes{})by(device,host_ip))*100`},
	}
	// 第一步,读取配置参数.
	configfile := flag.String("c", "config.yml", "config file")
	flag.Parse()
	Config := ReadYamlFile(*configfile)
	// 设置全局变量.
	ROBOTKEY = Config.RobotKey
	fmt.Println(Config)

	// for _, query := range Config.Querys {
	// 	querys = append(querys, query)
	// }
	querys = append(querys, Config.Querys...)

	for _, q := range querys {
		fmt.Println(q.MetricName)
	}

	var buffer bytes.Buffer
	buffer.WriteString(Config.InfoTitle + "\n")
	for _, query := range querys {
		fmt.Println("查询指标:", query.MetricName)
		fmt.Println("查询语句", query.PromQL)
		Resp, err := GetDatas(Config.PromQueryUrl, query.PromQL)
		if err != nil {
			fmt.Println("Get Data Error :", err)
			buffer.WriteString(fmt.Sprintf("查询 %s 失败 \n", query.MetricName))
			continue
		}
		switch query.MetricScope {
		case Cluster:
			f, _ := strconv.ParseFloat(Resp.Data.Result[0].Value[1].(string), 64)
			buffer.WriteString(fmt.Sprintf(query.MetricName+": \t %.2f%% \n", f))
		case Node:
			buffer.WriteString(query.MetricName + ": \n")
			for _, Res := range Resp.Data.Result {
				f, _ := strconv.ParseFloat(Res.Value[1].(string), 64)
				buffer.WriteString(fmt.Sprintf("%s \t %.2f%% \n", Res.Metric.HostIP, f))
			}
		case Pod:
			// TODO
		default:
			buffer.WriteString("")
		}
	}
	fmt.Println(buffer.String())
	// TODO
	SendQywxTextMsg(buffer.String(), Config.RobotKey)
}

type AppConfig struct {
	RobotKey     string  `yaml:"RobotKey"`
	PromQueryUrl string  `yaml:"PromQueryUrl"`
	Querys       []Query `yaml:"Querys"`
	InfoTitle    string  `yaml:"InfoTitle"`
}

func ReadYamlFile(configfile string) AppConfig {
	dataBytes, _ := os.ReadFile(configfile)
	log.Println("配置文件: \n", string(dataBytes))
	config := AppConfig{}
	yaml.Unmarshal(dataBytes, &config)
	return config
}

func GetDatas(promurl string, query string) (*Response, error) {
	url := promurl + "?query=" + query // 替换为实际的API地址
	response, err := http.Get(url)
	if err != nil {
		fmt.Println("Get Error:", err)
		return nil, err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		fmt.Println("IO Error:", err)
		return nil, err
	}

	var data Response
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println("Unmarshal Error:", err)
		return nil, err
	}
	if data.Status == "success" {
		for _, item := range data.Data.Result {
			hostIP := item.Metric.HostIP
			value := item.Value
			fmt.Printf("Host IP: %s, Value: %v\n", hostIP, value)
		}
	} else {
		fmt.Println("Error: Status is not success")
	}
	return &data, nil
}

// ===== 企业微信的通知
type TextMsg struct {
	MsgType        string          `json:"msgtype"`
	TextMsgContent *TextMsgContent `json:"text"`
}

type TextMsgContent struct {
	Content string `json:"content"`
}

func SendQywxTextMsg(msg string, defaultRobot string) (err error) {

	textmsg := &TextMsg{
		MsgType: "text",
		TextMsgContent: &TextMsgContent{
			Content: msg,
		},
	}

	data, err := json.Marshal(textmsg)
	if err != nil {
		return
	}
	var wechatRobotURL string

	wechatRobotURL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + defaultRobot

	req, err := http.NewRequest(
		"POST",
		wechatRobotURL,
		bytes.NewBuffer(data))

	if err != nil {
		return
	}

	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	resp, err := client.Do(req)

	if err != nil {
		return
	}

	defer resp.Body.Close()
	fmt.Println("response Status:", resp.Status)
	fmt.Println("response Headers:", resp.Header)

	return
}
